#include "thread.h"

using namespace el;

DWORD WINAPI Thread::threadProcess(LPVOID lpParam)
{
	Thread* thread = static_cast<Thread *>(lpParam);
	thread->run();
	return 0;
}

Thread::Thread()
{
	thread_ = NULL;
	thread_id_ = 0;
}


Thread::~Thread()
{
	if (thread_)
	{
		assert(false == isRunning());
		CloseHandle(thread_);
		thread_ = NULL;
		thread_id_ = 0;
	}
}

HANDLE el::Thread::start(const Functor& process)
{
	assert(false == isRunning());
	if (NULL != thread_)
	{
		CloseHandle(thread_);
		thread_ = NULL;
		thread_id_ = 0;
	}
	process_ = process;
	thread_ = CreateThread(
		NULL,
		NULL,
		&Thread::threadProcess,
		this,
		NULL,
		&thread_id_
	);
	return thread_;
}

void el::Thread::wait()
{
	assert(thread_);
	if (!isRunning())
	{
		return;
	}
	DWORD rtn = WaitForSingleObject(thread_, INFINITE);
	assert(WAIT_OBJECT_0 == rtn);
}

HANDLE el::Thread::thread()
{
	return thread_;
}

Thread::ThreadId el::Thread::threadId()
{
	return thread_id_;
}

bool el::Thread::isRunning()
{
	DWORD code;
	bool ok = GetExitCodeThread(thread_, &code) != 0;
	if (!ok)
	{
		return false;
	}
	return STILL_ACTIVE == code;
}

void el::Thread::run()
{
	process_();
}

